package com.lanhai.utils;

/**
 * 生成指令数据的工具类
 * @author liangmin
 *
 */
public class CommandUtil {
	
	/**
	 * AGV与机台对接指令
	 * @param agvId
	 * @param type（传输类型）1、完成，2、上层传出，3、上层传入，4、下层传出，5、下层传入，6、上出下入，7、上入下出,12、下左传出，13、下左传入
	 * @param channelFlag
	 * @param channel
	 * @return
	 */
	public static byte[] transfer(int agvId, int type) {
		byte[] data = new byte[9];
		data[0] = (byte) 0xA1;// 包头
		data[1] = (byte) agvId;// 车号
		data[2] = (byte) 2;// 功能码：2（传输）
		data[4] = (byte) type;// 类型
		// 计算和检校
		byte addData = 0;
		for (int i = 0; i < data.length - 1; i++) {
			addData += data[i];
		}
		data[8] = addData;
		return data;
	}
	
	/**
	 * 触发agv启动/停车
	 * @param agvId
	 * @param startOrStop 1:暂停;2:启动;
	 * @return
	 */
	public static byte[] startOrStop(int agvId, int startOrStop) {
		byte[] data = new byte[9];
		data[0] = (byte) 0xA1;// 包头
		data[1] = (byte) agvId;// 车号
		data[2] = (byte) 3;//功能码
		data[5] = (byte) startOrStop;
		
		// 计算和检校
		byte addData = 0;
		for (int i = 0; i < data.length - 1; i++) {
			addData += data[i];
		}
		data[8] = addData;
		return data;
	}

	/**
	 * 向AGV指定行驶目的地或路径
	 * @param agvId
	 * @param pathNo(线路号)
	 * @param channelFlag
	 * @param agvType
	 * @return
	 */
	public static byte[] pathway(int agvId, int pathNo) {
		byte[] pathsNumber = intToByteArray(pathNo);
		byte[] data = new byte[9];
		data[0] = (byte) 0xA1;// 包头
		data[1] = (byte) agvId;// 车号
		data[2] = (byte) 1;//功能码
		data[3] = pathsNumber[3];
		data[7] = pathsNumber[2];
		// 计算和检校
		byte addData = 0;
		for (int i = 0; i < data.length - 1; i++) {
			addData += data[i];
		}
		data[8] = addData;
		return data;
	}
	
	/**
	 * 从指令数据中获取地标号
	 * @param data
	 * @return
	 */
	public static int getGuidepost4Data(byte[] data){ 
		/**
		 * 数据的第4位和第5位为地标号
		 * data[3]:当前站点底8位, data[4]:当前站点高8位
		 */
		byte[] gpArr = {data[3], data[4], 0, 0};
		int i = toIntL(gpArr);		
		return i;
	}

	/**
	 * 从指令数据中获取地图X座标
	 * @param data
	 * @return
	 */
	public static short getMapX4Data(byte[] data){ 
		/**
		 * 数据的第4位和第5位为地图X座标
		 * data[5]:当前地图X坐标底8位, data[6]:当前地图X坐标高8位
		 */
		byte[] gpArr = {data[5], data[6], 0, 0};
		short i = toIntL(gpArr);		
		return i;
	}	

	 /**
     * int到byte[] 由高位到低位
     * @param i 需要转换为byte数组的整行值。
     * @return byte数组
     */
    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[4];
        result[0] = (byte)((i >> 24) & 0xFF);
        result[1] = (byte)((i >> 16) & 0xFF);
        result[2] = (byte)((i >> 8) & 0xFF);
        result[3] = (byte)(i & 0xFF);
        return result;
    }
	
	/**
	 * 从指令数据中获取地图Y座标
	 * @param data
	 * @return
	 */
	public static short getMapY4Data(byte[] data){ 
		/**
		 * 数据的第6位和第7位为地图Y座标
		 * data[7]:当前地图Y坐标底8位, data[8]:当前地图Y坐标高8位
		 */
		byte[] gpArr = {data[7], data[8], 0, 0};
		short i = toIntL(gpArr);		
		return i;
	}
	
	/**
	 * 从指令数据中获取路线号
	 * @param data
	 * @return
	 */
	public static short getPath4Data(byte[] data){ 
		/**
		 * 数据的第3位为路线号
		 * data[3]:
		 */
		byte[] gpArr = {0,0,0,data[3]};
		short i = toIntH(gpArr);		
		return i;
	}
	
	/**
	 * 生成向机台发送的指令,到位[action:1],申请离开[action:2]
	 * @param line
	 * @param action
	 * @return
	 */
	public static byte[] informPark(String line, int action){
		byte[] data = new byte[8];
		byte bl = HexUtil.hexToByte(line)[0];
		data[0] = bl;//线别
		data[1] = (byte) action;//动作
		return data;
	}
	
	/**
	 * 生成向机台发送的指令,到位[action:1],申请离开[action:2]
	 * @param line
	 * @param action
	 * @param orderLen 
	 * @return
	 */
	public static byte[] informPark(String line, int action, int orderLen){
		byte[] data = new byte[8];
		byte bl = HexUtil.hexToByte(line)[0];
		data[0] = bl;//线别
		data[orderLen] = (byte) action;//动作
		return data;
	}
	
	/**
	 * 测试获取地标的数组下标
	 * @param args
	 */
	public static void main(String[] args){
//		List<Map<String, Object>> testList = new ArrayList<Map<String, Object>>();
//		Map<String, Object> map1 = new HashMap<String, Object>();
//		map1.put("item", 1);
//		map1.put("point", 5);
//		testList.add(map1);
//		Map<String, Object> map2 = new HashMap<String, Object>();
//		map2.put("item", 2);
//		map2.put("point", 4);
//		testList.add(map2);
//		Map<String, Object> map3 = new HashMap<String, Object>();
//		map3.put("item", 3);
//		map3.put("point", 3);
//		testList.add(map3);
//		Map<String, Object> map6 = new HashMap<String, Object>();
//		map6.put("point", 201);
//		testList.add(map6);		
//		Map<String, Object> map4 = new HashMap<String, Object>();
//		map4.put("item", 4);
//		map4.put("point", 2);
//		testList.add(map4);
//		Map<String, Object> map5 = new HashMap<String, Object>();
//		map5.put("item", 5);
//		map5.put("point", 1);
//		testList.add(map5);
//		int mp = 201;
//		int begin = 0;
//		for(int i = 0; i < testList.size(); i++){
//			Map<String, Object> m = testList.get(i);
//			if(mp == (Integer)m.get("point")){
//				begin = i;
//				break;
//			}
//		}
//		System.out.println(begin);
//		byte[] data = sendToAGVIO(258,1,1,0x12);
//		String dataStr = HexUtil.byte2HexStr(data);
//		System.out.println(dataStr);
//		byte[] data = toHH(299);
//		byte[] data = {0, 0, (byte)1,(byte)43};
//		int i = toIntH(data);
//		System.out.println(data[0] + "," + data[1] + "," + data[2] + "," + data[3]);
//		System.out.println(i);
//		String hexs = "01";
//		System.out.println(HexUtil.decodeHEX(hexs));
		
		//读取PLC写入值
		//String plcIp = station.getIpAddress();
		String plcIp = "192.168.250.1";
		//String pcIp = localIp;
	    String pcIp = "192.168.250.117";
		int action = 1;//fins读操作
		//int readTar = station.getReadTar();//PLC写入寄存器地址
		int readTar = 32413;
		//int port = station.getPort();//PLC接收端口
		int port = 9600;
		byte[] sendByte1 = CommandUtil.getFinsHead(plcIp, pcIp, action, readTar);
		UDPUtil.sendData4Fins(sendByte1, plcIp, port, action, 1);
		byte[] result1 = UDPUtil.sendData4Fins(sendByte1, plcIp, port, action, 1);
		System.out.println(result1);
		//logger.info("PLC写入值：" + HexUtil.byte2HexStr(result1));
		
	}

	//int 转 byte[]   低字节在前（低字节序）
	public static byte[] toLH(int n) {  
	  byte[] b = new byte[4];  
	  b[0] = (byte) (n & 0xff);  
	  b[1] = (byte) (n >> 8 & 0xff);  
	  b[2] = (byte) (n >> 16 & 0xff);  
	  b[3] = (byte) (n >> 24 & 0xff);  
	  return b;  
	}

	//int 转 byte[]   高字节在前（高字节序）
	public static byte[] toHH(int n) {  
	  byte[] b = new byte[4];  
	  b[3] = (byte) (n & 0xff);  
	  b[2] = (byte) (n >> 8 & 0xff);  
	  b[1] = (byte) (n >> 16 & 0xff);  
	  b[0] = (byte) (n >> 24 & 0xff);  
	  return b;  
	}

	//byte[] 转 int 低字节在前（低字节序）
	public static short toIntL(byte[] b){
		short res = 0;
		for(int i=0;i<b.length;i++){
			res += (b[i] & 0xff) << (i*8);
		}
		return res;
	}

	//byte[] 转 int 高字节在前（高字节序）
	public static short toIntH(byte[] b){
		short res = 0;
	    for(int i=0;i<b.length;i++){
	        res += (b[i] & 0xff) << ((3-i)*8);
	    }
	    return res;
	}

	public static byte[] getFinsHead(String plcIp, String pcIp, int action, int target){
		String plcNo = plcIp.substring(plcIp.lastIndexOf(".") + 1);
		String servNo = pcIp.substring(pcIp.lastIndexOf(".") + 1);
		//int x = 4700;//寄存器地址（10进制）
		byte[] headByte = new byte[18];
        //command frame header
		headByte[0] = (byte)0x80;//ICF
		headByte[1] = (byte)0x00;//RSV
		headByte[2] = (byte)0x02;//GCT, less than 8 network layers
		headByte[3] = (byte)0x00;//DNA, local network
		headByte[4] = CommandUtil.toLH(Integer.parseInt(plcNo))[0];//DA1(PLC网络号)
		headByte[5] = (byte)0x00;//DA2, CPU unit
		headByte[6] = (byte)0x00;//SNA, local network
		headByte[7] = CommandUtil.toLH(Integer.parseInt(servNo))[0];//SA1(PC网络号)
		headByte[8] = (byte)0x00;//SA2, CPU unit
		headByte[9] = (byte)0x00;//SID
		headByte[10] = (byte)0x01;//MRC
		headByte[11] = (byte) action;//SRC(读:1，写:2)
		headByte[12] = HexUtil.hexToByte("82")[0];//固定
		headByte[13] = CommandUtil.toLH(target)[1];//寄存器地址高位
		headByte[14] = CommandUtil.toLH(target)[0];//寄存器地址低位
		headByte[15] = (byte)0x00;//固定
		headByte[16] = (byte)0x00;//读取/写入数量高位
		headByte[17] = (byte)0x04;//读取/写入数量低位(取4个字，8个字节)
		return headByte;
	}
	
	public static byte[] getFinsWriteData(String plcIp, int pcPort, String pcIp, int action
			, int target, byte[] content){
		byte[] sendByte = new byte[26];
		byte[] headByte = getFinsHead(plcIp, pcIp, action, target);
		System.arraycopy(headByte, 0, sendByte, 0, headByte.length);
		System.arraycopy(content, 0, sendByte, 18, content.length);
		return sendByte;
	}
	
	
}
